from __future__ import division
from math import radians
import math
import pygame
from vector import Vector

from OpenGL import GL as ogl

FULL_CIRCLE = radians(360)
DIRECTIONS = (Vector((0, 1, 0)), Vector((1, 0, 0)), Vector((0, -1, 0)), Vector((-1, 0, 0))) * 3

class Game(object):
	def __init__(self, heightmap):
		self.heightmap = heightmap
		self.viewangle = -90+360
		self.viewzoom = 1/10
		self.viewshift = Vector((0, 0, 0))
		self.axonometric = True
		self.shift = False
		self.held = {
			pygame.K_LSHIFT: False,
			pygame.K_LEFT: False,
			pygame.K_RIGHT: False,
			pygame.K_UP: False,
			pygame.K_DOWN: False}
		
		self.cursor_cell = Vector((0, 0, 0))
		
		for unit in self.heightmap.units:
			if unit.colour == (0, 0, 1):
				self.selected = unit
				break
		else:
			self.selected = None
	
	def update(self):
		if self.held[pygame.K_LSHIFT]:
			sin = math.sin(radians(self.viewangle+90))
			cos = math.cos(radians(self.viewangle+90))
			hshift = Vector((-cos, -sin, 0)) / self.viewzoom
			sin = math.sin(radians(self.viewangle))
			cos = math.cos(radians(self.viewangle))
			vshift = Vector((-cos, -sin, 0)) / self.viewzoom
		
		if self.held[pygame.K_RIGHT]:
			if self.held[pygame.K_LSHIFT]:
				self.viewshift += hshift
			else:
				self.viewangle += 3
				if self.viewangle > 360:
					self.viewangle -= 360
		elif self.held[pygame.K_LEFT]:
			if self.held[pygame.K_LSHIFT]:
				self.viewshift -= hshift
			else:
				self.viewangle -= 3
				if self.viewangle < 0:
					self.viewangle += 360
		elif self.held[pygame.K_UP]:
			if self.held[pygame.K_LSHIFT]:
				self.viewshift -= vshift
			else:
				self.viewzoom *= 1.1	
		elif self.held[pygame.K_DOWN]:
			if self.held[pygame.K_LSHIFT]:
				self.viewshift += vshift
			else:
				self.viewzoom /= 1.1
	
	def draw(self, surface):
		self.heightmap.render(self.viewangle, self.viewzoom, self.viewshift, self.axonometric)
		
		size = Vector((self.heightmap.width / 2, self.heightmap.height / 2, 0))
		position = (self.cursor_cell - size + Vector((0.5, 0.5, 0))) * 16
		ogl.glBegin(ogl.GL_LINE_LOOP)
		ogl.glVertex3f(*position + Vector((8, 8, 0)))
		ogl.glVertex3f(*position + Vector((-8, 8, 0)))
		ogl.glVertex3f(*position + Vector((-8, -8, 0)))
		ogl.glVertex3f(*position + Vector((8, -8, 0)))
		ogl.glEnd()
		
		if self.selected is not None:
			turntime = 60 * 5
			reachable, starts = self.heightmap.pathing.reachable(self.selected, turntime)
			s = self.heightmap.tilesize
			w, h = self.heightmap.width / 2, self.heightmap.height / 2
		
			ogl.glPointSize(1)
			ogl.glBegin(ogl.GL_POINTS)
			for position, time in reachable.iteritems():
				x, y = position
				cx, cy = (x-w+0.5)*s, (y-h+0.5)*s
				z = self.heightmap.unit_heights[y][x] + 1
				
				x2, y2 = starts[position]
				cx2, cy2 = (x2-w+0.5)*s, (y2-h+0.5)*s
				z2 = self.heightmap.unit_heights[y2][x2] + 1
				
				ogl.glColor3f((time/turntime), 1-(time/turntime), 0)
				ogl.glVertex3f(cx, cy, z)
			ogl.glEnd()
			
			if self.cursor_cell[:2] in reachable:
				ogl.glLineWidth(2)
				ogl.glShadeModel(ogl.GL_SMOOTH)
				ogl.glBegin(ogl.GL_LINES)
				start = tuple(self.cursor_cell)[:2]
				while start != self.selected.position:
					x, y = start
					cx, cy = (x-w+0.5)*s, (y-h+0.5)*s
					z = self.heightmap.unit_heights[y][x] + 1
				
					x2, y2 = starts[start]
					cx2, cy2 = (x2-w+0.5)*s, (y2-h+0.5)*s
					z2 = self.heightmap.unit_heights[y2][x2] + 1
				
					time = reachable[start]
					ogl.glColor3f((time/turntime), 1-(time/turntime), 0)
					ogl.glVertex3f(cx, cy, z)
				
					time = reachable[starts[start]]
					ogl.glColor3f((time/turntime), 1-(time/turntime), 0)
					ogl.glVertex3f(cx2, cy2, z2)
					start = starts[start]
				ogl.glEnd()
				ogl.glShadeModel(ogl.GL_FLAT)
				ogl.glLineWidth(1)
		
		return []
	
	def event(self, event):
		if event.type == pygame.QUIT:	
			quit = True
		elif event.type == pygame.KEYDOWN:
			offset = int(round((self.viewangle + 90) / 90))
			up, right, down, left = DIRECTIONS[-offset-4:-offset]
			
			self.held[event.key] = True	
			if event.key == pygame.K_TAB:
				self.axonometric = not self.axonometric
			elif event.key == pygame.K_KP8:
				if self.held[pygame.K_LSHIFT]:
					if self.selected:
						x, y = self.selected.position
						x, y, z = Vector((x, y, 0)) + up
						self.selected.position = x, y
				else:
					self.cursor_cell += up
			elif event.key == pygame.K_KP6:
				if self.held[pygame.K_LSHIFT]:
					if self.selected:
						x, y = self.selected.position
						x, y, z = Vector((x, y, 0)) + right
						self.selected.position = x, y
				else:
					self.cursor_cell += right
			elif event.key == pygame.K_KP2:
				if self.held[pygame.K_LSHIFT]:
					if self.selected:
						x, y = self.selected.position
						x, y, z = Vector((x, y, 0)) + down
						self.selected.position = x, y
				else:
					self.cursor_cell += down
			elif event.key == pygame.K_KP4:
				if self.held[pygame.K_LSHIFT]:
					if self.selected:
						x, y = self.selected.position
						x, y, z = Vector((x, y, 0)) + left
						self.selected.position = x, y
				else:
					self.cursor_cell += left
			elif event.key == pygame.K_KP_ENTER:
				self.selected.position = self.cursor_cell[0:2]
		elif event.type == pygame.KEYUP:
			self.held[event.key] = False
	
	def quit(self):
		pass
		
